

function transfromToUnderlined(str) {
    return [].reduce.call(str, (prv, cur, index) => {
        if (/[A-Z]/.test(cur)) {
            if (index === 0) {
                return prv + cur;
            } else {
                return prv + '_' + cur;
            }
        } else {
            return prv + cur;
        }
    })
}

function transfromToStateName(name) {
    let flag = false
    let stateName = name.split('').map((v, i) => {
        if (/[A-Z]/.test(v)) flag = true
        if (!flag) return ''
        return v
    }).join('')
    return stateName[0].toLowerCase() + stateName.substr(1)
}

/**
 * 快速创建api action相关的vuex module
 * @param {*} obj 
 * @returns {actions, mutations, state}
 */
export function createApiModule(obj) {
    const actions = {}
    const mutations = {}
    const state = {}
    const getters = {}
    for (let key in obj) {
        const func = typeof obj[key] === 'function' ? obj[key] : () => { }
        const mutationName = transfromToUnderlined(key).toUpperCase()
        const stateName = transfromToStateName(key)
        const stateValue = typeof obj[key] === 'object' ? obj[key].default : []
        const dataKey = obj[key].dataKey ?? 'data'
        actions[key] = async function ({
            commit
        }, ...params) {
            return new Promise(async (resolve, reject) => {
                let res, data
                try {
                    if (typeof obj[key] === 'object' && typeof obj[key].handler === 'function') {
                        res = (await obj[key].handler(...params, commit))
                    } else {
                        res = (await func(...params))
                    }
                    data = res
                    if (res?.data) data = dataKey ? res.data[dataKey] : res.data
                } catch (err) {
                    reject(err)
                }
                commit(mutationName, data)
                resolve(res)
            })
        }
        mutations[mutationName] = (state, data) => {
            state[stateName] = data
        }
        state[stateName] = stateValue
        getters[stateName] = state => state[stateName]
    }

    return {
        namespaced: true,
        actions,
        mutations,
        state,
        getters,
    }
}